/*
*	This is the Conflict Deal Unit
*	
*/

module Conflict_Deal(
	//input condition
	RsD,
	RtD,
	RsE,
	RtE,
	WriteRegE,
	WriteRegM,
	WriteRegW,
	BranchD,
	MemtoRegE,
	MemtoRegM,
	RegWriteE,
	RegWriteM,
	RegWriteW,
	
	//output control signal
	StallF,
	StallD,
	ForwardAD,
	ForwardBD,
	ForwardAE,
	ForwardBE,
	FlushE,
	
	//SMC Dealer
	SMCOccurLev1,
	SMCOccurLev2,
	SMCAddr,
	PCPlus4E,
	ALUOutE,
	MemWriteE
);
	input[4:0] RsD,RtD,RsE,RtE,WriteRegE,WriteRegM,WriteRegW;
	input BranchD,MemtoRegE,MemtoRegM,RegWriteE,RegWriteM,RegWriteW,MemWriteE;
	input[31:0] PCPlus4E,ALUOutE;
	
	output 	StallF,StallD,ForwardAD,ForwardBD,FlushE,SMCOccurLev1,SMCOccurLev2;
	output[1:0] ForwardAE,ForwardBE;
	output[31:0] SMCAddr;
	
	wire lwstall,branchstall;
	wire CFAE1,CFAE2,CFBE1,CFBE2;
	
	assign ForwardAD = (RsD != 0) && (RsD == WriteRegM) && RegWriteM;
	assign ForwardBD = (RtD != 0) && (RtD == WriteRegM) && RegWriteM;
	
	assign lwstall = (RtE!=0) &&((RsD == RtE) || (RtD == RtE)) && MemtoRegE;
	assign branchstall = (BranchD && RegWriteE && (WriteRegE == RsD || WriteRegE == RtD)) ||
							(BranchD && MemtoRegM && (WriteRegM == RsD || WriteRegM == RtD));
	//TODO will be changed if add j instruction
	
	assign StallF = lwstall || branchstall;
	assign StallD = lwstall || branchstall;
	
	assign FlushE = lwstall || branchstall || SMCOccurLev1;
	
	assign CFAE1 = (RsE != 0) && ((RsE == WriteRegM) && RegWriteM);
	assign CFAE2 = (RsE != 0) && ((RsE == WriteRegW) && RegWriteW);
	assign ForwardAE = CFAE1 == 1 ? 2'b10 : (CFAE2 == 1? 2'b01 : 2'b00);
	
	assign CFBE1 = (RtE != 0) && ((RtE == WriteRegM) && RegWriteM);
	assign CFBE2 = (RtE != 0) && ((RtE == WriteRegW) && RegWriteW);
	assign ForwardBE = CFBE1 == 1 ? 2'b10 : (CFBE2 == 1? 2'b01 : 2'b00);
	
	assign SMCOccurLev1 = MemWriteE && (ALUOutE == PCPlus4E);
	assign SMCOccurLev2 = MemWriteE && (ALUOutE == PCPlus4E + 4);
	
	assign SMCAddr = SMCOccurLev1 ? PCPlus4E :
						(SMCOccurLev2 ? (PCPlus4E + 4) : 0);
	
	/*
	always @(StallF) begin
			$display("time = %0d, StallF!",$time);
			$display("time = %0d, StallF = %d",$time,StallF);
			$display("time = %0d, lwstall = %d",$time,lwstall);
			$display("time = %0d, branchstall = %d",$time,branchstall);
			$display("time = %0d, BranchD = %d",$time,BranchD);
			$display("time = %0d, RegWriteE = %d",$time,RegWriteE);
			$display("time = %0d, WriteRegE = %d",$time,WriteRegE);
			$display("time = %0d, MemtoRegM = %d",$time,MemtoRegM);
	end
	//*/
	
endmodule
